package com.glp.work.flow.service.impl;

import com.alibaba.fastjson.JSON;
import com.glp.fbs.api.dto.user.PersonInfoDto;
import com.glp.work.flow.constant.APICode;
import com.glp.work.flow.constant.Constants;
import com.glp.work.flow.constant.OrderStatus;
import com.glp.work.flow.dto.OrderInfoDTO;
import com.glp.work.flow.exception.APIException;
import com.glp.work.flow.mapper.*;
import com.glp.work.flow.pojo.*;
import com.glp.work.flow.service.OrderInfoService;
import com.glp.work.flow.service.UserService;
import com.glp.work.flow.service.WfUserBusinessRangeService;
import com.glp.work.flow.service.WfUserSuperiorService;
import com.glp.work.flow.utils.DateUtils;
import com.glp.work.flow.utils.IDUtils;
import com.glp.work.flow.workflow.plugin.flowable.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 动态表单信息处理
 *
 * @author pengjia
 * @version 2020年3月9日 下午3:28:48
 */
@Slf4j
@Service
public class WfOrderServiceImpl implements OrderInfoService {

    @Autowired
    public WfOrderMapper wfOrderMapper;
    @Autowired
    public WfOrderDetailMapper wfOrderDetailMapper;
    @Autowired
    public RepositoryService repositoryService;
    @Resource
    WfUserSuperiorService wfUserSuperiorService;
    @Autowired
    private WfTaskAssignMapper wfTaskAssignMapper;
    @Autowired
    private WfTaskAssignUsersMapper wfTaskAssignUsersMapper;
    @Autowired
    private WfTaskAssignRoleMapper wfTaskAssignRoleMapper;
    @Resource
    private WfUserBusinessRangeService wfUserBusinessRangeService;
    @Resource
    private UserService userService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String saveOrderInfo(OrderInfoDTO dfDto) {
        WfOrder record = new WfOrder();
        record.setAppId(dfDto.getAppId());
        record.setProcDefKey(dfDto.getProcDefKey());
        record.setProcessId(dfDto.getProcessId());
        record.setOrderId(dfDto.getOrderId());
        record.setWfId(IDUtils.getWfId(dfDto.getAppId()));
        record.setOrderTitle(dfDto.getOrderTitle());
        record.setIndex_1(dfDto.getIndex_1());
        record.setIndex_2(dfDto.getIndex_2());
        record.setIndex_3(dfDto.getIndex_3());
        ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(dfDto.getProcDefKey()).latestVersion().singleResult();
        if (definition != null) {
            record.setProcDefName(definition.getName());
        }
        record.setCurrentInstance(dfDto.getCurrentInstance());
        record.setCurrentNode(dfDto.getCurrentNode());
        record.setCreateUserNo(dfDto.getUserId());
        PersonInfoDto personInfo = null;
        if (StringUtils.isBlank(dfDto.getUserName()) && StringUtils.isNoneBlank(dfDto.getUserId())) {
            personInfo = userService.getPersonInfo(dfDto.getUserId(), dfDto.getAppId());
            if (personInfo != null) {
                record.setCreateUser(personInfo.getName());
            }
        } else {
            record.setCreateUser(dfDto.getUserName());
        }
        record.setUpdateUser(dfDto.getUserName());
        record.setCreateTime(DateUtils.getCurrent());
        record.setUpdateTime(DateUtils.getCurrent());
        WfOrderDetail detail = new WfOrderDetail();
        detail.setProcessId(dfDto.getProcessId());
        if (dfDto.getDynamicForm() != null && !dfDto.getDynamicForm().isEmpty()) {
            detail.setBody(JSON.toJSONString(dfDto.getDynamicForm()));
        }
        detail.setCreateUser(dfDto.getUserId());
        detail.setUpdateUser(dfDto.getUserName());
        detail.setCreateTime(DateUtils.getCurrent());
        detail.setUpdateTime(DateUtils.getCurrent());
        record.setRemarks(dfDto.getRemarks());
        record.setBatch(dfDto.getBatch());
        log.info("保存工单主表信息");
        wfOrderMapper.insertSelective(record);
        log.info("保存工单子表信息");
        wfOrderDetailMapper.insertSelective(detail);
        log.info("开始保存业务范围信息");
        saveBusinessScope(dfDto, record, personInfo);
        return record.getWfId();
    }

    private void saveBusinessScope(OrderInfoDTO dfDto, WfOrder record, PersonInfoDto personInfo) {
        WfTaskAssign wfTaskAssign = new WfTaskAssign();
        wfTaskAssign.setProcDefKey(record.getProcDefKey());
        List<WfTaskAssign> wfTaskAssignList = wfTaskAssignMapper.select(wfTaskAssign);
        log.info("查询当前流程所有节点是否有按提交人业务范围分配");
        for (WfTaskAssign taskAssign : wfTaskAssignList) {
            if (taskAssign.getTaskDefRule() != null) {
                if (Constants.STATUS_1.equals(taskAssign.getTaskDefRule())) {
                    if (StringUtils.isEmpty(dfDto.getBusinessScopebCode())
                            && (personInfo == null || CollectionUtils.isEmpty(personInfo.getBusinessRangeCodes()))) {
                        log.error("无业务范围信息，请传入业务范围重新发起");
                        throw new APIException(APICode.WORKFLOW_SUMBIT_FAIL, "创建工单数据失败,请传入业务范围重新发起！");
                    }
                    log.info("保存业务范围信息");
                    WfUserBusinessRange wfUserBusinessRange = new WfUserBusinessRange();
                    wfUserBusinessRange.setAppId(record.getAppId());
                    wfUserBusinessRange.setProcessId(dfDto.getProcessId());
                    if (StringUtils.isNotBlank(dfDto.getBusinessScopebCode())) {
                        log.info("根据传入业务范围保存信息...{},{}", wfUserBusinessRange, dfDto.getBusinessScopebCode());
                        wfUserBusinessRange.setBusinessScopeCode(dfDto.getBusinessScopebCode());
                        wfUserBusinessRangeService.insertUserNo(wfUserBusinessRange);
                    } else if (personInfo != null && CollectionUtils.isNotEmpty(personInfo.getBusinessRangeCodes())) {
                        log.info("根据用户业务范围保存信息...{}", personInfo);
                        List<String> businessRangeCodes = personInfo.getBusinessRangeCodes();
                        String businessRangeCode = businessRangeCodes.toString();
                        String substring = businessRangeCode.substring(1, businessRangeCode.length() - 1);
                        wfUserBusinessRange.setBusinessScopeCode(substring);
                        wfUserBusinessRangeService.insertUserNo(wfUserBusinessRange);
                    }
                    break;
                }
            }
        }
        for (WfTaskAssign taskAssign : wfTaskAssignList) {
            if (taskAssign.getTaskDefId().equals(record.getCurrentInstance()) && Constants.STATUS_3.equals(taskAssign.getTaskDefRule())) {
                log.info("保存用户上级信息{}", personInfo);
                if (personInfo != null) {
                    WfUserSuperior wfUserSuperior = new WfUserSuperior();
                    wfUserSuperior.setUserNo(dfDto.getUserId());
                    wfUserSuperior.setSuperiorNo(personInfo.getParentUserNo());
                    wfUserSuperiorService.insertUserNo(wfUserSuperior);
                }
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateRejectOrderToProcessing(OrderInfoDTO orderDto, WfOrder wfOrder) {
        if (wfOrder != null) {
            //更新工单主表
            wfOrder.setOrderStatus(OrderStatus.PROCESSING.getCode());
            wfOrder.setUpdateUser(orderDto.getUserName());
            wfOrder.setUpdateTime(DateUtils.getCurrent());
            wfOrder.setOrderTitle(orderDto.getOrderTitle());
            wfOrder.setIndex_1(orderDto.getIndex_1());
            wfOrder.setIndex_2(orderDto.getIndex_2());
            wfOrder.setIndex_3(orderDto.getIndex_3());
            wfOrderMapper.updateByPrimaryKeySelective(wfOrder);
        }
        Example exampleDetail = new Example(WfOrderDetail.class);
        exampleDetail.createCriteria()
                .andEqualTo("processId", orderDto.getProcessId());
        WfOrderDetail recordDetail = wfOrderDetailMapper.selectOneByExample(exampleDetail);
        if (recordDetail != null) {
            //更工单子表-动态表单信息
            if (orderDto.getDynamicForm() != null && !orderDto.getDynamicForm().isEmpty()) {
                recordDetail.setBody(JSON.toJSONString(orderDto.getDynamicForm()));
            }
            recordDetail.setUpdateUser(orderDto.getUserName());
            recordDetail.setCreateTime(DateUtils.getCurrent());
            recordDetail.setUpdateTime(DateUtils.getCurrent());
            wfOrderDetailMapper.updateByPrimaryKeySelective(recordDetail);
        }
    }

    @Override
    public void updateWfOrder(String processId, WfOrder record) {
        Example example = new Example(WfOrder.class);
        example.createCriteria().andEqualTo("processId", processId);
        WfOrder wfOrder = wfOrderMapper.selectOneByExample(example);
        if (wfOrder != null) {
            Date createTime = wfOrder.getCreateTime();
            String distanceTime = DateUtil.getDistanceTime(DateUtils.getCurrent().getTime() - createTime.getTime());
            record.setTotalTime(distanceTime);
        }
        wfOrderMapper.updateByExampleSelective(record, example);
    }

    @Override
    public List<WfTaskAssignUsers> queryTaskAssignUsers(String proDefId, String taskDefKey) {
        log.info("获取任务分配用户信息");
        List<WfTaskAssignUsers> userList = new ArrayList<>();
        {
            Example example1 = new Example(WfTaskAssign.class);
            example1.createCriteria()
                    .andEqualTo("procDefId", proDefId)
                    .andEqualTo("taskDefId", taskDefKey);
            WfTaskAssign taskAssign = wfTaskAssignMapper.selectOneByExample(example1);
            if (taskAssign == null) {
                return new ArrayList<>();
            }
            Example example2 = new Example(WfTaskAssignUsers.class);
            example2.createCriteria().andEqualTo("mainId", taskAssign.getId());
            List<WfTaskAssignUsers> users = wfTaskAssignUsersMapper.selectByExample(example2);
            if (CollectionUtils.isNotEmpty(users)) {
                userList.addAll(users);
            }
        }
        return userList;
    }

    @Override
    public List<WfTaskAssignRole> queryTaskAssignRoles(String proDefId, String taskDefKey) {
        log.info("获取任务分配角色信息");
        List<WfTaskAssignRole> roleList = new ArrayList<>();
        {
            Example example1 = new Example(WfTaskAssign.class);
            example1.createCriteria()
                    .andEqualTo("procDefId", proDefId)
                    .andEqualTo("taskDefId", taskDefKey);
            WfTaskAssign taskAssign = wfTaskAssignMapper.selectOneByExample(example1);
            if (taskAssign == null) {
                return new ArrayList<>();
            }
            Example example2 = new Example(WfTaskAssignRole.class);
            example2.createCriteria().andEqualTo("mainId", taskAssign.getId());
            List<WfTaskAssignRole> roles = wfTaskAssignRoleMapper.selectByExample(example2);
            if (CollectionUtils.isNotEmpty(roles)) {
                roleList.addAll(roles);
            }
        }
        return roleList;
    }

    @Override
    public WfOrder queryWfOrderByPorcessId(String processId) {
        WfOrder record = new WfOrder();
        record.setProcessId(processId);
        return wfOrderMapper.selectOne(record);
    }

}
